package com.xxc.exam.service.impl

import com.fasterxml.jackson.databind.node.BigIntegerNode
import com.xxc.common.const.NOW
import com.xxc.common.exceptions.ParameterInvalidException
import com.xxc.exam.entity.CategoryEntity
import com.xxc.batis.vo.PageVO
import com.xxc.exam.entity.QuestionEntity
import com.xxc.exam.entity.pojo.Category
import com.xxc.exam.entity.pojo.Question
import com.xxc.batis.qo.PageQO
import com.xxc.exam.entity.vo.QuestionVO
import com.xxc.exam.mapper.CategoryMapper
import com.xxc.exam.mapper.QuestionMapper
import com.xxc.exam.service.QuestionService
import com.xxc.batis.ext.startPage
import com.xxc.batis.service.MysqlCrudServiceImpl
import com.xxc.exam.entity.dto.QuestionBatchDto
import com.xxc.exam.entity.pojo.Contest
import com.xxc.exam.entity.pojo.SelectionQues
import com.xxc.exam.entity.vo.ContestQuesVO
import com.xxc.exam.entity.vo.SelectionQuesVO
import com.xxc.exam.mapper.ContestMapper
import com.xxc.exam.mapper.SelectionQuesMapper
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.lang.StringBuilder
import java.math.BigInteger
import kotlin.IllegalArgumentException


@Service
class QuestionServiceImpl:QuestionService, MysqlCrudServiceImpl<Question,QuestionMapper>(){

    @Autowired
    lateinit var selectionQuesMapper: SelectionQuesMapper

    @Autowired
    lateinit var contestMapper: ContestMapper

    override fun getContestQues(id:BigInteger): List<ContestQuesVO> {
        val selections = selectionQuesMapper.select(
                SelectionQues(paperId = contestMapper.selectByPrimaryKey(id).paperId))
        val data = ArrayList<ContestQuesVO>()
        var index = 0
        selections.forEach {
            crudMapper.selectQuesBySelection(it.type!!, it.categories!!, mapOf(Pair(1, it.simpleCount!!),
                        Pair(2, it.normalCount!!),
                        Pair(3, it.complexCount!!)))
                    .forEach { ques ->
                        ques.id?.let { qid ->
                            data.add(ContestQuesVO(content = ques.title,
                                    index = ++index,
                                    selectionId = it.id,
                                    id = qid,
                                    options = ques.options,
                                    type = ques.type,
                                    answer = ques.answer))
                        }
                    }
        }
        return data
    }

    override fun countCategoriesQues(categories: List<BigInteger>, id: BigInteger, type: Int): HashMap<Int, Int> {
        val map = HashMap<Int,Int>()
        crudMapper.categoriesQuesCounts(categories,id,type).forEach{
            map[it.key!!] = it.value!!
        }
        return map
    }

    override fun updateQuestions(questions: QuestionBatchDto) {
        crudMapper.batchUpdate(questions)
    }

    @Autowired
    lateinit var categoryMapper: CategoryMapper

//    @CacheEvict(allEntries = true)
    override fun updateQuestion(question: Question) {
        if(question.id == null)
            throw IllegalArgumentException("更新题目时的题目id不能为空")
        if(crudMapper.existsWithPrimaryKey(QuestionEntity(question.id)))
        {
            crudMapper.updateByPrimaryKeySelective(question)
        } else {
           throw ParameterInvalidException("无法更新该题目，该题目不存在")
        }
    }

//    @CacheEvict(allEntries = true)
    override fun addQuestions(entityList: List<QuestionEntity>) {
        // 检查当前用户是否已创建该名称的分类，若未创建则创建
        val questions = List<Question>(entityList.size) { Question() }
        entityList.forEachIndexed { index,entity ->
            val question = questions[index]
            BeanUtils.copyProperties(entity,question)
            question.creatorId = entity.creator?.id?:throw IllegalArgumentException("添加试题时创建者id必须指定")
            entity.category?.let { category:CategoryEntity ->
                // 转换后的POJO
                val reflectedCate = Category(name = category.name, ownerId = category.owner?.id)
                // 查询数据库中是否已存在
                val innerCategory = categoryMapper.
                        selectOne(reflectedCate)
                if(innerCategory != null)
                {
                    // 若存在则将id设置给要插入的题目
                    question.categoryId = innerCategory.id
                }else
                {
                    reflectedCate.gmtCreate = NOW()
                    reflectedCate.gmtModified = NOW()
                    categoryMapper.insertSelective(reflectedCate)
                    question.categoryId = reflectedCate.id
                }
            }
        }
            // 将处理后的questions插入
        crudMapper.insertList(questions)
    }


//    @CacheEvict(allEntries = true)
    override fun delQuestions(questionIds: Array<BigInteger>) {
        if(questionIds.isEmpty())
            throw IllegalArgumentException("请保证至少有一个题目的id")
        if(questionIds.size == 1)
        {
            crudMapper.deleteByPrimaryKey(questionIds[0])
        }else
        {
            val sb = StringBuilder()
            questionIds.forEach {
                sb.append(it).append(',')
            }
            crudMapper.deleteByIds(sb.deleteCharAt(sb.length - 1).toString())
        }
    }

//    @Cacheable(key = "targetClass + methodName +#p0")
    override fun findWithPage(pageQO: PageQO<Question>): PageVO<QuestionVO> {
        val toVO = startPage<QuestionEntity,QuestionVO>(pageQO)
        if(pageQO.condition == null)
                crudMapper.selectAllEntities()
        else
            crudMapper.selectEntitiesByCondition(pageQO.condition!!)
        return toVO{entity->
            QuestionVO.map(entity)
        }
    }

}